安卓开发文档翻译:配置构建变种,Configure Build Variants
本文档页面,在 构建过程配置概述 的基础上更进一步,说明了 :如 何 配置构建变种 ,以实现在单个项目中创建出不同的应用版本; 以及,如何正确 地管理依赖关系和签名配置。
每个 构建变种 , 都代表着妳的应用程序的一个不同版本。例如 ,妳可能需要给妳的应用程序构建出一个免费版 ,其中的内容受限, 而同时构建出另一个付费 版,其中包含更多内容。或者 ,也可以构建出不同的应用程序版本,以用于支持不同的设备 ,基于不同的应用接口编程级别,或基于其它方面的设备特征。但是,如果 妳需要根据设备的应用程序二进制接口或屏幕密度来构建不同的版本的话,那么,就必须采用 构建多个APK 手段。
构建变种 ,实际上是在Gradle 中使用 特殊规则集合 产生的结果。具体来说,这些规则会根据 妳的构建类型和产品风味(flavor)中的配置来使用不同的设置、代码和资源。尽管 妳不会直接配置构建变种,但是,妳 会配置构建类型和产品风味,这二者结合组成了构建变种。
例如,对于"demo" (“演示”) 这个 产品风味 , 可以指定不同的特性及设备要求,比如说自定义的源代码、资源和最小应用编程接口级别, 同时,对于 "debug" (“调试”)这个 构建类型 ,又会使用不同的构建及打包选项,比如说开启调试选项 及使用调试用的签名密钥。二者组合 ,产生的构建变种就是, 会构建出应用程序的 "demoDebug" (“演示调试”) 版本 ,其中包含 着由"demo"产品风味、"debug"构建类型和 main/ 源代码集合组合而成的配置及资源。
妳可以在模块级别的 build.gradle 文件中的 android 代码块中创建及配置构建类型。 当妳创建一个新的模块时, Android Studio 会自动为妳创建对应的调试(debug)及发布(release)两种构建类型。尽管调试 式构建类型不会出现在构建配置文件中,但是, Android Studio 会对它配置出 可调试( debuggable true ) 选项。 这样,妳就能够在一个安全的安卓设备上调试妳的应用,并且会配置为使用一个通用的调试密钥来对APK 进行签名。
如果 妳想要添加或修改某些特定的选项,那么,妳仍然可以将调试构建类型加入到配置中。 以下示例中,对于调试 的构建类型指定了一个应用程序编号后缀( applicationIdSuffix ),并且 还配置出了一个 "jnidebug"构建类型 ,后者是以调试型构建类型中的选项为基础的。
android {
...
defaultConfig {...}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
applicationIdSuffix ".debug"
}
/**
* 'initWith'属性 ,可用于从其它的构建类型中复制得到配置选项,
* 这样,妳就不需要从头开始写配置了。然后 ,妳就只需要配置那些妳想要变动的选项了。
* 以下这一行,以调试型构建类型为基础初始化了'jnidebug',
* 然后仅仅修改 了applicationIdSuffix 和versionNameSuffix 两个选项。
*/
jnidebug {
// 以下这一行,复制得到了可调试( debuggable )属性及调试型构建类型中的签名选项。
initWith debug
applicationIdSuffix ".jnidebug"
jniDebuggable true
}
}
}
注意 : 当妳对构建配置文件进行修改时, Android Studio 会要求妳根据 新的配置内容对项目进行同步。 要对项目进行同步的话,有两种方式: 当妳做出修改时,通知 栏会显示出 Sync Now ,点击那个链接即可; 或者点击工具 栏中的 Sync Project 。
如果Android Studio 在妳的配置文件中检查出任何错误,就会弹出 Messages 窗口,说明问题。
欲学习所有能够在构建类型中配置的属性,则阅读 构建类型领域语言参考 。
创建产品风味 ,就跟创建构建类型类似: 将它们添加到 productFlavors 代码块中,再配置妳想修改的选项即可。产品风味 ,支持 defaultConfig 中所有的属性 — 这是因为, defaultConfig 实际 上是属于 ProductFlavor 类。 这就意味着, 妳可以在 defaultConfig 代码块中提供针对所有风味的基础配置, 再对每个风味 , 对其中对应的默认值进行改变,例如 applicationId 。 欲了解更多关于应用程序编号的信息,则阅读 设置应用程序编号 。
注意 : 妳仍然需要在 main/ 代码集合的清单文件中使用 package 属性来指定一个包名。并且 ,妳也必须在妳的源代码中使用该个包名 , 来引用 R 类 , 或解析所有 的相对的活动 (activity) 及服务 (service) 类的注册声明。 这样, 妳就可以使用 applicationId 为每个产品风味赋予一个唯一的打包和分发编号, 而无需修改源代码。
以下代码示例,创建了"demo"和"full"两个产品风味,它们分别提供 了各自独有的 applicationIdSuffix 和 versionNameSuffix 属性:
android {
...
defaultConfig {...}
buildTypes {...}
productFlavors {
demo {
applicationIdSuffix ".demo"
versionNameSuffix "-demo"
}
full {
applicationIdSuffix ".full"
versionNameSuffix "-full"
}
}
}
注意 : 要想利用Google Play 中的 多 APK支持功能 来分发妳的应用的话,那么 ,应当 对所有的变种都赋予相同的 applicationId 值, 但使用不同的 versionCode 。 要想在Google Play 中 将应用的不同变种分发为各自独立的应用,则,应当 为每个变种赋予一个不同的 applicationId 。
创建 及配置好了产品风味之后,就点击通知栏中的 Sync Now 文字。 在同步完成之后, Gradle 就会自动根据妳的构建类型和产品风味来创建各自构建变种,并且根据 <product-flavor><Build-Type> 的规则对它们进行命名。例如, 妳创建了 'demo' 和 'full'两个产品风味 ,并且保留了默认的 'debug' 和 'release'构建类型 ,则, Gradle 会创建以下的构建变种:
•. demoDebug
•. demoRelease
•. fullDebug
•. fullRelease
妳可以将构建变种切换成妳想要构建及运行的任何一个 — 具体做法 就是,点击 Build > Select Build Variant ,然后在下拉菜单中选择一个。然而 ,要想对每个构建变种独有的特性及资源进行自定义的话,妳就需要知道该如何创建及管理源代码集合。
某些情况下,妳可能想要将来自多个产品风味的配置选项组合起来。例如,妳可能想要根据应用编程接口级别的不同,来为"full"和"demo"两个产品风味创建不同的配置选项。为了实现这一点,Gradle 的Android 插件实现了对应的功能,使得妳能够创建产品风味组,称为风味维度(dimension)。在构建应用程序时,Gradle会从妳定义的每个风味维度中组合出对应产品风味的配置选项,再与当前的构建类型中的配置组合起来,以创建出最终的构建变种。Gradle并不会将属于同一个风味维度的不同产品风味组合起来。
提示 : 要想做到根据不同的应用程序二进制接口和屏幕密度来创建不同的应用程序分发版本的话, 妳应当使用 构建多个APK 手段,而不是产品风味。
以下代码示例中,利用 了 flavorDimensions 属性来做文章:创建 了一个"mode"风味维度,用于 将"full"和"demo"两个产品风味分组 到一起; 另有一个"api"风味维度,用于根据应用程序编程接口级别 来将不同的产品风味分组到一起。
android {
...
buildTypes {
debug {...}
release {...}
}
// 在此处指定妳想要使用的风味维度。 妳列出各个维度的顺序,将决定它们的优先级,
// 从最高到最低,
// 这会进而影响到 Gradle合并各个变种 的源代码和配置选项时的行为。对于 妳配置的每个产品风味,
// 都必须将它赋予到某个风味维度中。
flavorDimensions "api", "mode"
productFlavors {
demo {
// 将这个产品风味赋予到 "mode"风味维度 中。
dimension "mode"
...
}
full {
dimension "mode"
...
}
// 在各个"api"产品风味中配置的选项, 会覆盖掉在各个"mode"产品风味
// 及defaultConfig 代码块中配置的选项。 Gradle 会根据各个维度
// 在flavorDimensions 属性中出现的顺序来决定它们的优先级
// --第一 个维度的优先级大于第二个维度,依次类推。
minApi24 {
dimension "api"
minSdkVersion '24'
// 要想确保目标设备接收到具有最高 相兼容应用编程接口级别的应用程序版本的话,
// 则,赋予版本 号代码时应当与应用编程接口级别相关联且递增。
// 欲了解更多关于利用版本 号代码来支持应用程序更新及向Google Play 中上传的信息,则,
versionCode 30000 + android.defaultConfig.versionCode
versionNameSuffix "-minApi24"
...
}
minApi23 {
dimension "api"
minSdkVersion '23'
versionCode 20000 + android.defaultConfig.versionCode
versionNameSuffix "-minApi23"
...
}
minApi21 {
dimension "api"
minSdkVersion '21'
versionCode 10000 + android.defaultConfig.versionCode
versionNameSuffix "-minApi21"
...
}
}
}
...
Gradle 最终创建的构建变种的个数,等于,每个风味维度中的风味的个数与妳所配置的构建类型个数之间的乘积。当Gradle对各个构建变种及对应的APK 进行命名时,属于较高优先级风味维度的产品风味会先出现,接下来时属于较低优先级风味维度的产品风味,接下来是构建类型。继续拿上面那个构建配置内容来说,Gradle一共会创建12个构建变种,分别是以下名字模式:
构建变种 : [minApi24, minApi23, minApi21][Demo, Full][Debug, Release]
对应 的 APK : app-[minApi24, minApi23, minApi21]-[demo, full]-[debug, release].apk
例如,
构建变种 : minApi24DemoDebug
对应 的 APK : app-minApi24-demo-debug.apk
妳不仅仅 可以为每个单独的产品风味和构建类型创建出各自的源代码集合目录, 还可以为产品风味 的每种 组合 创建出各自的源代码集合目录。例如 ,妳可以创建 src/demoMinApi24/java/ 目录,并且向其中加入Java 代码, 这样,仅仅 在构建出一个组合了这两个产品风味的构建变种时,Gradle 才会使用那些代码。针对产品风味组合 而创建的源代码集合,其优先级, 要高于针对单个产品风味而创建的源代码集合。 欲了解 更多关于源代码集合以及Gradle 对资源的合并过程的信息,则阅读如何 创建 源代码集合 小节。
对于 妳创建的 产品风味 和构建类型的每种可能的组合, Gradle 都 会创建 一个对应的构建变种。然而 ,可能有某些构建变种,它们要么是妳根本不需要的,要么是对于妳的项目来说无意义的。对于 这种情况,妳可以在模块级别的 build.gradle 文件中创建 出一个变种过滤器, 以去除特定的构建变种。
仍然 拿前一小节中的构建配置文件来举例,假设,对于妳的应用的演示(demo)版本, 妳仅仅打算支持应用编程接口级别 23 及更高版本 的系统 。那么 ,妳就可以利用 variantFilter 代码块,过滤 掉所有会将"minApi21"和"demo"产品风味组合起来的构建变种:
android {
...
buildTypes {...}
flavorDimensions "api", "mode"
productFlavors {
demo {...}
full {...}
minApi24 {...}
minApi23 {...}
minApi21 {...}
}
variantFilter { variant ->
def names = variant.flavors*.name
// 要检查某个特定的构建类型,则使用 variant.buildType.name == " <buildType> "
if (names.contains("minApi21") && names.contains("demo")) {
// Gradle 会忽略掉任何满足上述条件的变种 。
setIgnore(true)
}
}
}
...
当妳在构建配置中加入了变种过滤器,并且点击了通知栏中的 Sync Now 之后,Gradle就会忽略掉任何满足妳所指定条件的构建变种了,于是,那些构建变种再也不会在妳点击菜单栏中 Build > Select Build Variant (或工具窗口条中的 Build Variants )的时候出现在下拉菜单中了。
默认情况 下, Android Studio 会创建一个 main/ 源代码集合 ,以及对应的目录,其中包含 着所有妳想要在全部构建变种中共享的东西。然而 ,妳 也可以创建新的源代码集合,以针对特定的构建类型、产品风味( 当 使用风味维度 时,还有产品风味的组合 )和构建变种来精确地控制,哪些文件 将 被Gradle 所编译及打包。例如 ,妳可以在 main/ 那个源代码集合中定义下基本的功能, 再使用产品风味源代码集合来针对 不同的客户改变妳的应用程序的品牌,或者仅仅 在那些带有调试型构建类型的构建变种中包含特殊的权限及日志功能。
Gradle希望 妳按照特定的方式组织源代码集合中的文件和目录,其组织方式与 main/ 源代码集合类似。例如, Gradle期待 着, 与"debug"构建类型相关的Java 类文件,应当被放置在 src/debug/java/ 目录中。
Gradle 的安卓插件中,提供了一个狠有用的Gradle任务,它会显示出,对于妳的每个构建类型、产品风味和构建变种,应当将各种文件如何组织。例如,以下输出内容片断中,说明了,对于"debug"这种构建类型,Gradle期待着到哪里找到特定的文件:
------------------------------------------------------------
Project :app
------------------------------------------------------------
...
debug
----
Compile configuration: compile
build.gradle name: android.sourceSets.debug
Java sources: [app/src/debug/java]
Manifest file: app/src/debug/AndroidManifest.xml
Android resources: [app/src/debug/res]
Assets: [app/src/debug/assets]
AIDL sources: [app/src/debug/aidl]
RenderScript sources: [app/src/debug/rs]
JNI sources: [app/src/debug/jni]
JNI libraries: [app/src/debug/jniLibs]
Java-style resources: [app/src/debug/resources]
要想生成及查看关于妳的构建配置的这项报告,则,按照以下步骤进行:
1. 点击集成开发环境窗口右侧 的 Gradle 。
2. 依次展开 MyApplication (这里实际上会是妳的应用的项目名字) > Tasks > android ,再双击 sourceSets 。
3. 要查看最终报告,则点击集成开发环境窗口底部的 Gradle Console 。
注意 : 这个报告中, 还会显示出, 为了对妳的应用运行测试,该如何组织源代码集合中的文件,比如 test/ 和 androidTest/ 两个 测试 用源代码集合 。
当妳创建一个新的构建变种时, Android Studio 并不会为妳创建对应的源代码集合目录, 但它提供了一些功能,用于帮助妳正确地放置文件。例如 ,要想为"debug"这个构建类型创建 java/ 目录的话:
1. 打开 Project 面板 , 在面板的顶部,选中下拉菜单中的 Project 视图。
2. 浏览 到 MyProject (注意,这里替换 成 妳的实际项目名字) /app/src/ 。
3. 右击 src 目录 ,再选择 New > Folder > Java Folder 。
4. 单击 Target Source Set 旁边 的下拉菜单,选择 debug 。
5. 单击 Finish 。
Android Studio 会 为妳的debug 构建类型创建一个源代码集合目录,然后 在其中创建 java/ 目录。或者 ,换种方式, 当妳为某个特定的构建变种添加新文件时,可以让Android Studio 为妳创建对应的目录。例如 ,要为"debug"构建类型创建一个包含值的XML 文件,则:
1. 还是在那个 Project 面板中,右击 src 目录 ,然后选择 New > XML > Values XML File 。
2.输入XML 文件的名字,或者保留默认文件名。
3. 单击 Target Source Set 旁边 的下拉菜单,选择 debug 。
4. 点击 Finish 。
因为"debug"构建类型被指定为目标源代码集合,所以,Android Studio在创建XML 文件时自动创建了必要的目录。由此产生的目录结构如下图所示。
图 2. 针对debug 构建类型创建 的新的源代码集合。
利用 这种方式,妳 还 可以 为产生风味创建源代码集合目录,例如 src/demo/ ,也可以为构建变种创建源代码集合目录,例如 src/demoDebug/ 。另外 ,妳还可以为特定 的构建变种创建测试用源代码集合,例如 src/androidTestDemoDebug/ 。 欲了解更多细节,则阅读 测试 用源代码集合 。
如果妳的某些源代码 并不是按照Gradle 所预期的默认源代码集合文件结构组织起来的, 也就是说,它们并不是位于 上一小节 创建 源代码集合 中说明的位置,那么 , 妳可以使用 sourceSets 代码块来说明,对于 该个源代码集合中的各个组件,Gradle 应当到哪里去寻找文件。 妳不需要将这些文件移动位置; 妳只需要向Gradle 指定这些路径,指定相对于模块级别 build.gradle 文件的路径,Gradle 就会到那些位置去找源代码集合中各个组件的文件。 要想了解有哪些组件是可以配置的,以及它们是否可以被映射到多个文件或目录,则,阅读 Gradle 的安卓插件的领域语言参考 。
以下代码示例, 将 app/other/ 目录中的源代码文件映射 到了 main 源代码集合中的特定组件,并且,改变了 androidTest 源代码集合的根目录。
android {
...
sourceSets {
// 此处 是针对main 源代码集合的配置选项。
main {
// 改变Java 源代码的目录。默认目录 是
// 'src/main/java' 。
java.srcDirs = ['other/java']
// 如果 妳列出了多个目录,则, Gradle 会将它们全部用上,以从中收集源代码。
// 因为Gradle 给这些目录赋予了相同的优先级,所以,如果
// 妳在多个目录中定义了相同的资源的话,就会在合并资源时引发一个错误。
// 默认目录 是 'src/main/res' 。
res.srcDirs = ['other/res1', 'other/res2']
// 注意 : 应当避免 将已指定的一个或多个目录的亲代目录也指定到集合中。
// 例如 ,避免以下代码:
// res.srcDirs = ['other/res1', 'other/res1/layouts', 'other/res1/strings']
// 正确 的做法是,仅仅指定根目录'other/res1',
// 或者仅仅指定其中的'other/res1/layouts'和'other/res1/strings'两个嵌套目录。
// 对于每个 源代码集合,只能指定一个安卓清单文件。
// 默认情况 下, Android Studio 会在src/main/目录中为main 源代码集合创建对应的清单文件。
manifest.srcFile 'other/AndroidManifest.xml'
...
}
// 创建其它 的代码块,以对其它的源代码集合进行配置。
androidTest {
// 如果某个 源代码集合的所有文件都位于某个单个根目录下,
// 那么 ,妳就可以使用setRoot 属性来指定那个根目录。
// 在为这个源代码集合收集源代码文件时, Gradle 只会在相对于妳所指定的根目录的路径中寻找文件。
// 例如 , 在为androidTest 源代码集合应用了以下配置选项之后,
// Gradle 就只会在src/tests/java/目录中寻找Java源代码文件了。
setRoot 'src/tests'
...
}
}
}
...
妳可以利用源代码集合目录来包含那些只希望在特定配置条件下被打包的源代码和资源。例如,在构建"demoDebug"这个构建变种时,由于它是"demo"产品风味和"debug"构建类型的组合变种,所以,Gradle会在以下目录中寻找,并且为它们赋予以下优先级:
1. src/demoDebug/ (构建变种对应 的源代码集合 )
2. src/debug/ (构建类型对应 的源代码集合 )
3. src/demo/ (产品风味对应 的源代码集合 )
4. src/main/ (main 源代码集合 )
注意 : 如果妳 组合 了多个产品风味 ,那么 ,各个产品风味之间的优先级顺序取决于它们所属于的风味维度。 当妳使用 android.flavorDimensions 属性来列出风味维度时,属于第一 个风味维度的那些产品风味,其优先级高于那些属于第二个风味维度的产品风味,依次类推。另外 ,通过 将产品风味组合而产生的源代码集合,其优先级比其中各个单个产品风味的源代码集合的优先级要高。
以上列出的顺序,决定了,当Gradle 对代码和资源进行组合时,哪些源代码集合具有更高的优先级。由于 demoDebug/ 源代码集合中可能包含了只对那个构建变种有意义的文件,所以,如果 demoDebug/ 中包含了一个同时也在 debug/ 中定义了的文件的话, Gradle 会使用 demoDebug/ 源代码集合中的那个文件。类似 于,对于构建类型和产品风味源代码集合中的文件,Gradle 会赋予其相对于 main/ 中同名文件更高的优先级。 Gradle 在应用以下构建规则时,会将以上优先级规则计算在内:
•. java/ 目录 中的所有源代码,会编译到一起,生成一个单一的输出文件。
注意: 对于每个特定 的构建变种,如果 Gradle 发现跟它相关的两个或多个源代码集合中定义 了同一个Java 类,那么,会抛出一个构建错误。例如, 在构建调试版( debug ) APK 时, 就不能同时定义 src/debug/Utility.java 和 src/main/Utility.java 。 这是因为,在构建过程中, Gradle 会到这两个目录中去寻找源代码文件,并在我们所举例子的情况下抛出一个“类定义重复”('duplicate class')错误。如果 妳希望在不同的构建类型中使用不同的 Utility.java 版本,那么, 可以在每个构建类型源代码集合目录中定义其特有的版本, 而不将文件放置到 main/ 源代码集合中。
•. 多个清单文件 会被合并,形成一个单一的清单文件。优先 级顺序,与前面所说的列表相同。 也就是说,针对构建类型而编写的清单文件选项,会覆盖掉针对产品风味 而编写的清单文件选项,如此类推。欲了解更多细节,则阅读 清单文件合并 。
•. 类似 地,那些 values/ 目录中的文件也会被合并到一起。如果两个文件具有相同 的名字,例如两个 strings.xml 文件,那么 , 其优先级顺序,与之前列表中给出的优先级顺序相同。 也就是说,在构建类型源代码集合中某个文件里定义的那些值,其优先级,高于在产品风味源代码集合中同名文件里定义的那些值,如此类推。
•. res/ 和 asset/ 目录中的那些资源,会被打包到一起。如果 在两个或多个源代码集合中出现了具有相同名字的资源,则,其优先级顺序,与之前所述列表中相同。
•.最后,在构建APK 时,对于库模块依赖项中包含的资源及清单文件,Gradle给予最低的优先级。
妳可以 为特定的构建变种或 测试 用源代码集合 配置独有的依赖,具体做 法就是, 在 Compile 关键字前面加上构建变种 或测试用源代码集合的名字,如下所示。
dependencies {
// 对于"free"产品风味 ,将本地的"mylibrary"模块添加为一个依赖。
freeCompile project(":mylibrary")
// 对于fullRelease 和fullDebug 构建变种, 将特定的库模块依赖添加为编译期依赖。
fullReleaseCompile project(path: ':library', configuration: 'release')
fullDebugCompile project(path: ':library', configuration: 'debug')
// 添加 一个远程二进制依赖,仅用于本地测试。
testCompile 'junit:junit:4.12'
// 添加 一个远程二进制依赖,仅用于 标注过的(instrumented)测试APK。
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
}
欲了解更多信息,则阅读 添加构建依赖 。
对于 发布型(release)构建类型的APK, 除非 妳 为 它显式地定义好签名配置 ,否则 , Gradle 不会对它进行签名。 妳可以轻松地创建一个发布用密钥并且 使用 Android Studio 来对发布型构建类型进行签名 。
可以手动利用Gradle 构建配置来为发布型构建类型配置好签名选项:
1. 创建 一个密钥存储。 密钥存储 ( keystore ),是一个二进制文件,其中包含有多个私钥。 妳必须将私钥放置在一个安全且可靠的地方。
2. 创建 一个私钥。 私钥 ( private key ),代表 着这个应用背后的实体,例如某个人或某个公司。
3. 将签名配置添加到模块级别的 build.gradle 文件中:
...
android {
...
defaultConfig {...}
signingConfigs {
release {
storeFile file("myreleasekey.keystore")
storePassword "password"
keyAlias "MyReleaseKey"
keyPassword "password"
}
}
buildTypes {
release {
...
signingConfig signingConfigs.release
}
}
}
要生成经签名的 APK ,则,点击菜单栏中的 Build > Generate Signed APK 。然后 ,文件 app/build/apk/app-release.apk 中的软件包,就会使用发布型密钥签名了。
注意 : 在构建配置文件中写入发布用密钥和密钥存储文件的密码, 是一件狠不安全的事。作为替代手段 ,妳可以对构建文件进行配置,让它 从环境变量中读取到这些密码,或者 在构建过程中提示妳亲自输出这些密码。
按照以下方式从环境变量中获取这些密码:
storePassword System.getenv("KSTOREPWD")
keyPassword System.getenv("KEYPWD")
在以命令行方式执行构建过程时,由构建过程提示妳亲自输入这些密码:
storePassword System.console().readLine("\nKeystore password: ")
keyPassword System.console().readLine("\nKey password: ")
在完成这个过程之后,就可以分发妳的应用了,也可以将它发布到Google Play。
警告 : 要将妳的密钥存储文件和私钥放置在一个安全且可靠的地方,并且要对它们进行安全的备份。如果 妳向Google Play 发布了一个应用之后,弄丢了那个用于对这个应用进行签名的密钥,那么,日后 就再也无法针对这个应用发布新版了,因为,同一个应用的所有版本都必须使用相同的密钥来签名。
在发布安卓穿带(Android Wear)应用时,妳会将穿带式应用打包到一个标准手持设备应用中去,这是因为,用户无法 在穿带式设备上直接浏览及安装应用。两个应用 都必须签名。 欲了解更多关于对安卓穿带应用进行打包及签名的信息,则阅读 打包 穿带应用 。
未知美人
黑夜传说 阿米莉亚
Your opinionsHxLauncher: Launch Android applications by voice commands